package com.bwie.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.pojo.Menu;
import com.bwie.pojo.User;
import com.bwie.service.UserService;
import com.bwie.mapper.UserMapper;
import com.bwie.state.CheckEnum;
import com.bwie.utils.R;
import com.bwie.vo.LoginForm;
import com.bwie.vo.PageInfoVo;
import com.github.tobato.fastdfs.FdfsClientConfig;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.yaml.snakeyaml.events.Event;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author 陈彤彤
* @description 针对表【t_user】的数据库操作Service实现
* @createDate 2025-04-23 08:16:01
*/
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    UserMapper userMapper;

    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 通过request获取token
     */
    @Autowired
    HttpServletRequest request;

    /**
     * 引入文件上传
     */
    @Autowired
    FastFileStorageClient fileStorageClient;

    /**
     * 用户分页列表
     * @param pageInfoVo
     * @return
     */
    @Override
    public R getUserList(PageInfoVo pageInfoVo) {
        //构造分页参数
        Page<User> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(User::getId);
        if (StringUtils.isNoneEmpty(pageInfoVo.getKeyWord())){
            wrapper.lambda().like(User::getUsername,pageInfoVo.getKeyWord())
                    .or().like(User::getPhone,pageInfoVo.getKeyWord())
                    .or().like(User::getEmail,pageInfoVo.getKeyWord())
                    .or().like(User::getNickName,pageInfoVo.getKeyWord());
        }

        //分页列表
        Page<User> userPage = userMapper.selectPage(page,wrapper);
        return R.OK(userPage);
    }

    /**
     * 管理员登录
     * @param loginForm
     * @return
     */
    @Override
    public R adminLogin(LoginForm loginForm) {
        /*获取用户信息*/
        User user= userMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getUsername,loginForm.getUsername()));
        //判断用户名是否存在
        if (user == null){
            return R.ERROR(404,"用户不存在");
        }

        /*校验密码*/
        //判断密码是否正确
        if (!user.getPassword().equals(loginForm.getPassword())){
            return R.ERROR(404,"密码错误");
        }

        /*生成token*/
        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "123456")
                .claim("id", user.getId())
                .claim("username",user.getUsername())
                .claim("nickName",user.getNickName())
                .compact();

        /*缓存token 过期时间为60分钟*/
        String redisToken = "token-" + user.getId();
        redisTemplate.opsForValue().set(redisToken,token,60, TimeUnit.MINUTES);

        /*返回token*/
        user.setToken(token);
        //将密码设置为空
        user.setPassword(null);

        return R.OK(user);
    }

    /**
     * 用户注册
     * @param user
     * @return
     */
    @Override
    public R userReg(User user) {
        /*校验用户名是否重复 (唯一性校验)*/
        User userOne = userMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getUsername, user.getUsername()));
        if (userOne != null){
            return R.ERROR(500,"用户名重复");
        }

        /*添加用户*/
        //注册时间
        user.setStartTime(new Date());
        userMapper.insert(user);
        return R.OK();
    }


    /**
     * 用户审核
     * @param user
     * @return
     */
    @Override
    public R checkUser(User user) {
        /*判断用户是否存在*/
        User selectById = userMapper.selectById(user.getId());
        if (selectById == null){
            return R.ERROR(404,"用户不存在");
        }

        /*如果审核驳回，必须填写审核理由 */
        if (user.getUserStatus().equals(CheckEnum.CHECK_NO.getCode())){
            //审核驳回，进行判断审核说明是否为空
            if (StringUtils.isEmpty(user.getReason())){
                //返回错误信息
                return R.ERROR(500,"审核驳回,必须填写审核说明");
            }
        }

        /*审核通过，修改审核状态为1(审核通过)   使用传过来的参数作为赋值*/
        selectById.setUserStatus(user.getUserStatus());
        selectById.setReason(user.getReason());
        userMapper.updateById(selectById);
        return R.OK();
    }

    /**
     * 获取我的信息（用户详情）
     * @return
     */
    @Override
    public R getMyInfo() {
        /*根据request获取token*/
        String token = request.getHeader("token");
        //判断
        if (token == null){
            return R.ERROR(500,"请先登录");
        }

        /*解析token*/
        Claims claims = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        //获取id
        Integer userId = claims.get("id", Integer.class);

        /*返回用户信息并返回*/
        User user = userMapper.selectById(userId);
        return R.OK(user);
    }

    /**
     * 修改用户信息
     * @param user
     * @return
     */
    @Override
    public R updateUser(User user) {
        //判断用户是否存在
        User selectById = userMapper.selectById(user.getId());
        if (selectById == null){
            return R.ERROR(404,"用户不不存在");
        }
        //如果用户存在，进行修改
        userMapper.updateById(user);
        return R.OK();
    }

    /**
     * 图片上传
     * @param file
     * @return
     */
    @Override
    public R uploadFile(MultipartFile file) {
        try {
            //扩展名通过工具类
            String extName = FileNameUtil.extName(file.getOriginalFilename());
            //上传
            StorePath storePath = fileStorageClient.uploadFile(file.getInputStream(), file.getSize(), extName, null);
            //图片路径
            String url = "http://192.168.80.192:8888/" + storePath.getFullPath();
            return R.OK(url);
        } catch (IOException e) {
            e.printStackTrace();
            return R.ERROR(500,"上传失败");
        }
    }

    /**
     * 单删用户信息
     * @param id
     * @return
     */
    @Override
    public R deleteUserById(Integer id) {
        //判断用户是否存在
        User user = userMapper.selectById(id);
        if (user == null){
            return R.ERROR(404,"用户不存在");
        }

        //存在则删除
        userMapper.deleteById(id);
        return R.OK();
    }

    /**
     * 获取当前用户角色列表
     * @return
     */
    @Override
    public R getUserRoleList() {
        /*解析token*/
        //获取token
        String token = request.getHeader("token");
        //判断是否token
        if(token == null){
            return R.ERROR(500,"请登录");
        }
        Claims claims = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        //获取用户id
        Integer userId = claims.get("id", Integer.class);

        /*获取用户角色列表*/
        List<String> userRoleList = userMapper.getUserRoleList(userId);

        return R.OK(userRoleList);
    }

    /**
     * 获取当前菜单树
     * @return
     */
    @Override
    public R getUserMenuTree() {
        /*解析token*/
        //获取token
        String token = request.getHeader("token");
        //判断是否token
        if(token == null){
            return R.ERROR(500,"请登录");
        }
        Claims claims = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        //获取用户id
        Integer userId = claims.get("id", Integer.class);
        /*获取菜单列表*/
        List<Menu> menuList = userMapper.getUserMenuTree(userId);

        /*构建菜单树*/
        List<Tree<String>> treeList = TreeUtil.build(menuList, "0", (menu, tree) -> {
            tree.setId(menu.getId() + "");
            tree.setName(menu.getName() + "");
            tree.setParentId(menu.getPid() + "");

            tree.putExtra("path",menu.getPath());
            tree.putExtra("title",menu.getTitle());
            tree.putExtra("component",menu.getComponent());
        });
        return R.OK(treeList);
    }
}




